﻿// -----------------------------------------------------------------------
// <copyright file="ElementPalette.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace FormCreator.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Windows.Input;
    using FormCreator.Model;
    using Microsoft.Practices.Prism.Commands;
    using Microsoft.Practices.Prism.ViewModel;
    using WPForms.Common.Model;

    /// <summary>
    /// Provides a list of all available <see cref="FormElement"/> classes.
    /// </summary>
    [Export]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class ElementPaletteViewModel : NotificationObject
    {
        /// <summary>
        /// The list of loaded assemblies.
        /// </summary>
        private IList<Assembly> loadedAssemblies = new List<Assembly>();

        /// <summary>
        /// Initializes a new instance of the <see cref="ElementPaletteViewModel" /> class.
        /// </summary>
        public ElementPaletteViewModel()
        {
            this.LoadAssembly("WPForms.Common.dll");
            this.LoadAssemblyCommand = new DelegateCommand(this.Load);
        }

        /// <summary>
        /// Gets the list of available form element types.
        /// </summary>
        public ReadOnlyCollection<ElementType> ElementTypes { get; private set; }

        /// <summary>
        /// Gets the command responsible for loading additional element assemblies.
        /// </summary>
        public ICommand LoadAssemblyCommand { get; private set; }

        /// <summary>
        /// Loads the all form elements from the given assembly.
        /// </summary>
        /// <param name="assemblyPath">The assembly path.</param>
        public void LoadAssembly(string assemblyPath)
        {
            if (assemblyPath == null)
            {
                throw new ArgumentNullException("assemblyPath");
            }

            this.loadedAssemblies.Add(System.Reflection.Assembly.LoadFrom(assemblyPath));
            var types = this.loadedAssemblies
                .SelectMany(a => a.GetTypes())
                .Where(t => typeof(FormElement).IsAssignableFrom(t) && !t.IsAbstract)
                .Select(t => new ElementType(t))
                .ToList();
            this.ElementTypes = new ReadOnlyCollection<ElementType>(types);
            this.RaisePropertyChanged(() => this.ElementTypes);
        }

        /// <summary>
        /// Pops up an open file dialog to select additional assemblies to load.
        /// </summary>
        private void Load()
        {
            var dialog = new Microsoft.Win32.OpenFileDialog()
            {
                Filter = "Assemblies(*.dll)|*.dll",
            };
            if (dialog.ShowDialog() == true)
            {
                this.LoadAssembly(dialog.FileName);
            }
        }
    }
}
